package com.sunwayworld.basemodule.rm.train.exampaper.service.impl;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.sunwayworld.basemodule.rm.train.exam.bean.LimsCoreExamBean;
import com.sunwayworld.basemodule.rm.train.exam.bean.LimsCoreExamQuestionBean;
import com.sunwayworld.basemodule.rm.train.exam.service.LimsCoreExamQuestionService;
import com.sunwayworld.basemodule.rm.train.exam.service.LimsCoreExamService;
import com.sunwayworld.basemodule.rm.train.exampaper.bean.LimsCoreExamPaperAnswerBean;
import com.sunwayworld.basemodule.rm.train.exampaper.bean.LimsCoreExamPaperBean;
import com.sunwayworld.basemodule.rm.train.exampaper.dao.LimsCoreExamPaperDao;
import com.sunwayworld.basemodule.rm.train.exampaper.service.LimsCoreExamPaperAnswerService;
import com.sunwayworld.basemodule.rm.train.exampaper.service.LimsCoreExamPaperService;
import com.sunwayworld.basemodule.rm.train.question.bean.LimsCoreQuestionBean;
import com.sunwayworld.basemodule.rm.train.question.service.LimsCoreQuestionService;
import com.sunwayworld.basemodule.rm.train.support.enums.LimsExamPaperStatus;
import com.sunwayworld.cloud.module.train.exampaper.bean.CoreExamPaperBean;
import com.sunwayworld.framework.data.page.Page;
import com.sunwayworld.framework.utils.*;
import com.sunwayworld.module.mdm.user.bean.CoreUserBean;
import com.sunwayworld.module.mdm.user.service.CoreUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;


import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.audit.aunnotation.Audit;
import com.sunwayworld.framework.audit.constant.AuditConstant;
import com.sunwayworld.framework.constant.Constant;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.i18n.I18nHelper;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;

@Repository
@GikamBean
public class LimsCoreExamPaperServiceImpl implements LimsCoreExamPaperService {

    @Autowired
    private LimsCoreExamPaperDao limsCoreExamPaperDao;

    @Autowired
    @Lazy
    private LimsCoreExamPaperAnswerService limsCoreExamPaperAnswerService;

    @Autowired
    @Lazy
    private LimsCoreExamService limsCoreExamService;

    @Autowired
    @Lazy
    private LimsCoreQuestionService limsCoreQuestionService;

    @Autowired
    @Lazy
    private LimsCoreExamQuestionService limsCoreExamQuestionService;

    @Autowired
    @Lazy
    private CoreUserService coreUserService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsCoreExamPaperDao getDao() {
        return limsCoreExamPaperDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    @Audit(AuditConstant.INSERT)
    public Long insert(RestJsonWrapperBean wrapper) {
        LimsCoreExamPaperBean coreExamPaperBean = wrapper.parseUnique(LimsCoreExamPaperBean.class);
        coreExamPaperBean.setId(ApplicationContextHelper.getNextIdentity());
        coreExamPaperBean.setExamPaperCode(ApplicationContextHelper.getNextSequence(getDao().getTable()));

        Long orderNo = 1L;
        List<LimsCoreExamQuestionBean> examQuestionList = limsCoreExamQuestionService.selectListByFilter(SearchFilter.instance().match("EXAMID", coreExamPaperBean.getExamId()).filter(MatchPattern.EQ));

        List<LimsCoreExamQuestionBean> singleChoiceExamQuestionList = examQuestionList.stream().filter(f -> "singleChoice".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());
        List<LimsCoreExamQuestionBean> multipleChoiceExamQuestionList = examQuestionList.stream().filter(f -> "multipleChoice".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());
        List<LimsCoreExamQuestionBean> judgementExamQuestionList = examQuestionList.stream().filter(f -> "judgement".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());
        List<LimsCoreExamQuestionBean> shortAnswerExamQuestionList = examQuestionList.stream().filter(f -> "shortAnswer".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());
        List<LimsCoreExamQuestionBean> completionExamQuestionList = examQuestionList.stream().filter(f -> "completion".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());

        List<LimsCoreExamPaperAnswerBean> coreExamPaperAnswerList = new ArrayList<>();

        if (!singleChoiceExamQuestionList.isEmpty()) {
            for (int i = 0; i < singleChoiceExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean singleChoiceExamQuestion = singleChoiceExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(singleChoiceExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(singleChoiceExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExamPaperBean.getExamId());
                coreExamPaperAnswer.setExamPaperId(coreExamPaperBean.getId());
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (!multipleChoiceExamQuestionList.isEmpty()) {
            for (int i = 0; i < multipleChoiceExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean multipleChoiceExamQuestion = multipleChoiceExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(multipleChoiceExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(multipleChoiceExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExamPaperBean.getExamId());
                coreExamPaperAnswer.setExamPaperId(coreExamPaperBean.getId());
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (!completionExamQuestionList.isEmpty()) {
            for (int i = 0; i < completionExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean completionExamQuestion = completionExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(completionExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(completionExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExamPaperBean.getExamId());
                coreExamPaperAnswer.setExamPaperId(coreExamPaperBean.getId());
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (!judgementExamQuestionList.isEmpty()) {
            for (int i = 0; i < judgementExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean judgementExamQuestion = judgementExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(judgementExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(judgementExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExamPaperBean.getExamId());
                coreExamPaperAnswer.setExamPaperId(coreExamPaperBean.getId());
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (!shortAnswerExamQuestionList.isEmpty()) {
            for (int i = 0; i < shortAnswerExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean shortAnswerExamQuestion = shortAnswerExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(shortAnswerExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(shortAnswerExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExamPaperBean.getExamId());
                coreExamPaperAnswer.setExamPaperId(coreExamPaperBean.getId());
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        getDao().insert(coreExamPaperBean);

        limsCoreExamPaperAnswerService.getDao().insert(coreExamPaperAnswerList);
        return coreExamPaperBean.getId();
    }

    @Override
    @Transactional
    public void submit(RestJsonWrapperBean wrapper) {
        List<LimsCoreExamPaperBean> coreExamPaperBeans = wrapper.parse(LimsCoreExamPaperBean.class);
        // 根据人员拆分考卷
        List<Long> examPaperIds = coreExamPaperBeans.stream().map(LimsCoreExamPaperBean::getId).collect(Collectors.toList());
        List<LimsCoreExamPaperAnswerBean> examPaperAnswerBeans = limsCoreExamPaperAnswerService.getDao().selectListByOneColumnValues(examPaperIds, "examPaperId");
        Map<Long, List<LimsCoreExamPaperAnswerBean>> answerMapList = examPaperAnswerBeans.stream().collect(Collectors.groupingBy(LimsCoreExamPaperAnswerBean::getExamPaperId));
        List<String> userIds = coreExamPaperBeans.stream().map(LimsCoreExamPaperBean::getExamUserId).collect(Collectors.toList());
        String userIdStr = StringUtils.join(userIds, ",");
        List<String> examUserIds = Arrays.stream(userIdStr.split(",")).distinct().collect(Collectors.toList());
        List<CoreUserBean> userBeans = coreUserService.selectListByIds(examUserIds);
        Map<String, String> useMap = userBeans.stream().collect(Collectors.toMap(CoreUserBean::getId, CoreUserBean::getUserName));
        List<LimsCoreExamPaperBean> insertExamPaperBeans = new ArrayList<>();
        List<LimsCoreExamPaperAnswerBean> insertExamPaperAnswerBeans = new ArrayList<>();
        for (LimsCoreExamPaperBean examPaperSource : coreExamPaperBeans) {
            String[] splitArr = examPaperSource.getExamUserId().split(",");
            List<Long> ids = ApplicationContextHelper.getNextIdentityList(splitArr.length);
            for (String userId : splitArr) {
                LimsCoreExamPaperBean examPaperTarget = new LimsCoreExamPaperBean();
                BeanUtils.copyProperties(examPaperSource, examPaperTarget, "id", "status");
                examPaperTarget.setId(ids.remove(0));
                examPaperTarget.setStatus("start");
                examPaperTarget.setUserId(userId);
                examPaperTarget.setUserName(useMap.get(userId));
                insertExamPaperBeans.add(examPaperTarget);
                List<LimsCoreExamPaperAnswerBean> coreExamPaperAnswerBeans = answerMapList.get(examPaperSource.getId());
                List<Long> answerIds = ApplicationContextHelper.getNextIdentityList(coreExamPaperAnswerBeans.size());
                for (LimsCoreExamPaperAnswerBean examPaperAnswerSource : coreExamPaperAnswerBeans) {
                    LimsCoreExamPaperAnswerBean examPaperAnswerTarget = new LimsCoreExamPaperAnswerBean();
                    BeanUtils.copyProperties(examPaperAnswerSource, examPaperAnswerTarget, "id", "examPaperId");
                    examPaperAnswerTarget.setId(answerIds.remove(0));
                    examPaperAnswerTarget.setExamPaperId(examPaperTarget.getId());
                    insertExamPaperAnswerBeans.add(examPaperAnswerTarget);
                }
            }
        }

        getDao().fastInsert(insertExamPaperBeans);
        limsCoreExamPaperAnswerService.getDao().fastInsert(insertExamPaperAnswerBeans);

        getDao().deleteBy(coreExamPaperBeans, "id");
        limsCoreExamPaperAnswerService.getDao().deleteBy(examPaperAnswerBeans, "id");
    }

    @Override
    @Transactional
    public void updateExamPaperUser(RestJsonWrapperBean wrapper) {
        List<LimsCoreExamPaperBean> examPaperBeans = wrapper.parse(LimsCoreExamPaperBean.class);
        getDao().update(examPaperBeans, "examUserId", "examUserName");
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.UPDATE)
    @Audit(AuditConstant.SAVE)
    public LimsCoreExamPaperBean startExam(RestJsonWrapperBean wrapper) {
        LimsCoreExamPaperBean examPaper = wrapper.parseUnique(LimsCoreExamPaperBean.class);

        LocalDateTime examBeginTime = examPaper.getExamBeginTime();
        LocalDateTime examEndTime = examPaper.getExamEndTime();
        LocalDateTime now = LocalDateTime.now();

        if (now.isBefore(examBeginTime)) {
            throw new InvalidDataException("CORE.MODULE.TRAIN.EXAM_PAPER.TIP.EXAM_NOT_BEGIN");
        }

        if (now.isAfter(examEndTime)) {
            throw new InvalidDataException("CORE.MODULE.TRAIN.EXAM_PAPER.TIP.EXAM_DONE");
        }

        examPaper.setActBeginTime(now);
        examPaper.setStatus(LimsExamPaperStatus.DONE.name().toLowerCase());
        getDao().update(examPaper, "ACTBEGINTIME", "STATUS");

        StringBuilder countDown = new StringBuilder();
        int examDuration = examPaper.getExamDuration().intValue();
        // 计算倒计时
        if (now.plusMinutes(examPaper.getExamDuration()).isAfter(examEndTime)) { // 当前时间+考试时长>考试结束时间
            int minitus = (int) now.until(examEndTime, ChronoUnit.MINUTES);
            countDown.append(StringUtils.leftPad(String.valueOf(minitus / 60), 2)).append(":");
            countDown.append(StringUtils.leftPad(String.valueOf(minitus % 60), 2));

        } else {
            countDown.append(StringUtils.leftPad(String.valueOf(examDuration / 60), 2)).append(":");
            countDown.append(StringUtils.leftPad(String.valueOf(examDuration % 60), 2));
        }
        examPaper.setExt$Item("countdown", countDown.toString());
        return examPaper;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.UPDATE)
    @Audit(AuditConstant.SAVE)
    public void endExam(RestJsonWrapperBean wrapper) {
        LimsCoreExamPaperBean coreExamPaper = wrapper.parseUnique(LimsCoreExamPaperBean.class);

        List<LimsCoreExamPaperAnswerBean> examPaperAnswerList = limsCoreExamPaperAnswerService.selectListByFilter(SearchFilter.instance().match("EXAMPAPERID", coreExamPaper.getId()).filter(MatchPattern.EQ)
                .match("QUESTIONTYPE", "shortAnswer").filter(MatchPattern.DIFFER));

        examPaperAnswerList.forEach(e -> {
            String answer = StringUtils.trim(e.getAnswer());
            if (StringUtils.isEmpty(answer)) {
                e.setScore(0L);
            } else {
                String correctAnswer = StringUtils.trim(e.getExt$Item("correctanswer"));
                if ("multipleChoice".equals(e.getExt$Item("questiontype"))) {
                    if (correctAnswer.length() == answer.length()) {
                        char[] correctAnswerArray = correctAnswer.toCharArray();
                        char[] answerArray = answer.toCharArray();
                        Arrays.sort(correctAnswerArray);
                        Arrays.sort(answerArray);

                        if (String.valueOf(correctAnswerArray).equals(String.valueOf(answerArray))) {
                            e.setScore(NumberUtils.parseLong(e.getExt$Item("multiplechoicescore")));
                        }
                    }
                } else {
                    if (StringUtils.equals(correctAnswer, answer)) {
                        if ("singleChoice".equals(e.getExt$Item("questiontype"))) {
                            e.setScore(NumberUtils.parseLong(e.getExt$Item("singlechoicescore")));
                        } else if ("judgement".equals(e.getExt$Item("questiontype"))) {
                            e.setScore(NumberUtils.parseLong(e.getExt$Item("judgementscore")));
                        } else if ("completion".equals(e.getExt$Item("questiontype"))) {
                            e.setScore(NumberUtils.parseLong(e.getExt$Item("completionscore")));
                        }
                    }
                }
            }
        });

        long score = examPaperAnswerList.stream().mapToLong(LimsCoreExamPaperAnswerBean::getScore).sum();
        coreExamPaper.setActEndTime(LocalDateTime.now());
        coreExamPaper.setScore(score);

        getDao().update(coreExamPaper, "ACTENDTIME", "SCORE");
        limsCoreExamPaperAnswerService.getDao().update(examPaperAnswerList, "SCORE");
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    @Audit(AuditConstant.INSERT)
    public void generateExamPaper(Long examId, Long trainId, String userId, String userName) {

        LimsCoreExamBean exam = limsCoreExamService.selectDetail(examId);

        if ("manual".equals(exam.getQuestionMethod())) {
            generateManualExamPaper(exam, trainId, userId, userName);
        } else {
            generateRandomExamPaper(exam, trainId, userId, userName);
        }
    }

    private void generateManualExamPaper(LimsCoreExamBean coreExam, Long trainId, String userId, String userName) {
        LimsCoreExamPaperBean coreExamPaper = new LimsCoreExamPaperBean();
        Long id = ApplicationContextHelper.getNextIdentity();

        coreExamPaper.setId(id);
        coreExamPaper.setExamId(coreExam.getId());
        coreExamPaper.setUserId(userId);
        coreExamPaper.setUserName(userName);
        coreExamPaper.setTrainId(trainId);

        Long orderNo = 1L;
        List<LimsCoreExamQuestionBean> examQuestionList = limsCoreExamQuestionService.selectListByFilter(SearchFilter.instance().match("EXAMID", coreExam.getId()).filter(MatchPattern.EQ));

        List<LimsCoreExamQuestionBean> singleChoiceExamQuestionList = examQuestionList.stream().filter(f -> "singleChoice".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());
        List<LimsCoreExamQuestionBean> multipleChoiceExamQuestionList = examQuestionList.stream().filter(f -> "multipleChoice".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());
        List<LimsCoreExamQuestionBean> judgementExamQuestionList = examQuestionList.stream().filter(f -> "judgement".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());
        List<LimsCoreExamQuestionBean> shortAnswerExamQuestionList = examQuestionList.stream().filter(f -> "shortAnswer".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());
        List<LimsCoreExamQuestionBean> completionExamQuestionList = examQuestionList.stream().filter(f -> "completion".equals(f.getExt$Item("questiontype"))).collect(Collectors.toList());

        List<LimsCoreExamPaperAnswerBean> coreExamPaperAnswerList = new ArrayList<>();

        if (!singleChoiceExamQuestionList.isEmpty()) {
            for (int i = 0; i < singleChoiceExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean singleChoiceExamQuestion = singleChoiceExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(singleChoiceExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(singleChoiceExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (!multipleChoiceExamQuestionList.isEmpty()) {
            for (int i = 0; i < multipleChoiceExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean multipleChoiceExamQuestion = multipleChoiceExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(multipleChoiceExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(multipleChoiceExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (!completionExamQuestionList.isEmpty()) {
            for (int i = 0; i < completionExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean completionExamQuestion = completionExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(completionExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(completionExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (!judgementExamQuestionList.isEmpty()) {
            for (int i = 0; i < judgementExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean judgementExamQuestion = judgementExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(judgementExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(judgementExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (!shortAnswerExamQuestionList.isEmpty()) {
            for (int i = 0; i < shortAnswerExamQuestionList.size(); i++) {
                LimsCoreExamQuestionBean shortAnswerExamQuestion = shortAnswerExamQuestionList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setExamQuestionId(shortAnswerExamQuestion.getId());
                coreExamPaperAnswer.setQuestionId(shortAnswerExamQuestion.getQuestionId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        getDao().insert(coreExamPaper);

        limsCoreExamPaperAnswerService.getDao().insert(coreExamPaperAnswerList);
    }

    private void generateRandomExamPaper(LimsCoreExamBean coreExam, Long trainId, String userId, String userName) {
        List<LimsCoreQuestionBean> questionList = limsCoreQuestionService.selectListByFilter(SearchFilter.instance().match("QUESTIONCATEGORY", coreExam.getExamCategory()).filter(MatchPattern.EQ)
                .match("ACTIVATEDFLAG", Constant.ACTIVATED_STATUS_YES).filter(MatchPattern.SEQ)
                .match("LASTSUSPENDEDFLAG", Constant.SUSPENDED_STATUS_NO).filter(MatchPattern.SEQ));

        List<LimsCoreQuestionBean> singleChoiceQuestionList = questionList.stream().filter(f -> "singleChoice".equals(f.getQuestionType())).collect(Collectors.toList());
        List<LimsCoreQuestionBean> multipleChoiceQuestionList = questionList.stream().filter(f -> "multipleChoice".equals(f.getQuestionType())).collect(Collectors.toList());
        List<LimsCoreQuestionBean> completionQuestionList = questionList.stream().filter(f -> "completion".equals(f.getQuestionType())).collect(Collectors.toList());
        List<LimsCoreQuestionBean> judgementQuestionList = questionList.stream().filter(f -> "judgement".equals(f.getQuestionType())).collect(Collectors.toList());
        List<LimsCoreQuestionBean> shortAnswerQuestionList = questionList.stream().filter(f -> "shortAnswer".equals(f.getQuestionType())).collect(Collectors.toList());

        boolean validFlag = true;
        StringBuilder validMessage = new StringBuilder();

        if (coreExam.getTmplSingleChoiceQty() > 0) {
            if (coreExam.getTmplSingleChoiceQty() > singleChoiceQuestionList.size()) {
                validMessage.append(I18nHelper.getMessage("CORE.MODULE.TRAIN.EXAM_PAPER.TIP.SINGLECHOICE_QUESTION_QTY_LESS_THAN_EXAM_SINGLECHOICE_QUESTION_QTY")).append("\n");
                validFlag = false;
            }
        }
        if (coreExam.getTmplMultipleChoiceQty() > 0) {
            if (coreExam.getTmplMultipleChoiceQty() > multipleChoiceQuestionList.size()) {
                validMessage.append(I18nHelper.getMessage("CORE.MODULE.TRAIN.EXAM_PAPER.TIP.MULTIPLECHOICE_QUESTION_QTY_LESS_THAN_EXAM_MULTIPLECHOICE_QUESTION_QTY")).append("\n");
                validFlag = false;
            }
        }

        if (coreExam.getCompletionQty() > 0) {
            if (coreExam.getCompletionQty() > completionQuestionList.size()) {
                validMessage.append(I18nHelper.getMessage("CORE.MODULE.TRAIN.EXAM_PAPER.TIP.COMPLETION_QUESTION_QTY_LESS_THAN_EXAM_COMPLETION_QUESTION_QTY")).append("\n");
                validFlag = false;
            }
        }

        if (coreExam.getTmplJudgementQty() > 0) {
            if (coreExam.getTmplJudgementQty() > judgementQuestionList.size()) {
                validMessage.append(I18nHelper.getMessage("CORE.MODULE.TRAIN.EXAM_PAPER.TIP.JUDGEMENT_QUESTION_QTY_LESS_THAN_EXAM_JUDGEMENT_QUESTION_QTY")).append("\n");
                validFlag = false;
            }
        }
        if (coreExam.getTmplShortAnswerQty() > 0) {
            if (coreExam.getTmplShortAnswerQty() > shortAnswerQuestionList.size()) {
                validMessage.append(I18nHelper.getMessage("CORE.MODULE.TRAIN.EXAM_PAPER.TIP.SHORTANSWER_QUESTION_QTY_LESS_THAN_EXAM_SHORTANSWER_QUESTION_QTY")).append("\n");
                validFlag = false;
            }
        }

        if (!validFlag) {
            throw new InvalidDataException(validMessage.toString());
        }

        LimsCoreExamPaperBean coreExamPaper = new LimsCoreExamPaperBean();
        Long id = ApplicationContextHelper.getNextIdentity();

        coreExamPaper.setId(id);
        coreExamPaper.setExamId(coreExam.getId());
        coreExamPaper.setUserId(userId);
        coreExamPaper.setUserName(userName);
        coreExamPaper.setTrainId(trainId);

        Long orderNo = 1L;

        List<LimsCoreExamPaperAnswerBean> coreExamPaperAnswerList = new ArrayList<>();

        if (coreExam.getTmplSingleChoiceQty() > 0) {
            List<LimsCoreQuestionBean> singleChoiceQuestionChoosenList = getRandomQuestion(singleChoiceQuestionList, coreExam.getTmplSingleChoiceQty());
            for (int i = 0; i < singleChoiceQuestionChoosenList.size(); i++) {
                LimsCoreQuestionBean singleChoiceQuestion = singleChoiceQuestionChoosenList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setQuestionId(singleChoiceQuestion.getId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (coreExam.getTmplMultipleChoiceQty() > 0) {
            List<LimsCoreQuestionBean> multipleChoiceQuestionChoosenList = getRandomQuestion(multipleChoiceQuestionList, coreExam.getTmplMultipleChoiceQty());
            for (int i = 0; i < multipleChoiceQuestionChoosenList.size(); i++) {
                LimsCoreQuestionBean multipleChoiceQuestion = multipleChoiceQuestionChoosenList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setQuestionId(multipleChoiceQuestion.getId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (coreExam.getTmplCompletionQty() > 0) {
            List<LimsCoreQuestionBean> completionQuestionChoosenList = getRandomQuestion(completionQuestionList, coreExam.getTmplCompletionQty());
            for (int i = 0; i < completionQuestionChoosenList.size(); i++) {
                LimsCoreQuestionBean multipleChoiceQuestion = completionQuestionChoosenList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setQuestionId(multipleChoiceQuestion.getId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (coreExam.getTmplJudgementQty() > 0) {
            List<LimsCoreQuestionBean> judgementQuestionChoosenList = getRandomQuestion(judgementQuestionList, coreExam.getTmplJudgementQty());
            for (int i = 0; i < judgementQuestionChoosenList.size(); i++) {
                LimsCoreQuestionBean judgementChoiceQuestion = judgementQuestionChoosenList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setQuestionId(judgementChoiceQuestion.getId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        if (coreExam.getTmplShortAnswerQty() > 0) {
            List<LimsCoreQuestionBean> shortAnswerChoiceQuestionChoosenList = getRandomQuestion(shortAnswerQuestionList, coreExam.getTmplShortAnswerQty());
            for (int i = 0; i < shortAnswerChoiceQuestionChoosenList.size(); i++) {
                LimsCoreQuestionBean shortAnswerQuestion = shortAnswerChoiceQuestionChoosenList.get(i);
                LimsCoreExamPaperAnswerBean coreExamPaperAnswer = new LimsCoreExamPaperAnswerBean();
                coreExamPaperAnswer.setId(ApplicationContextHelper.getNextIdentity());
                coreExamPaperAnswer.setQuestionId(shortAnswerQuestion.getId());
                coreExamPaperAnswer.setExamId(coreExam.getId());
                coreExamPaperAnswer.setExamPaperId(id);
                coreExamPaperAnswer.setOrderNo(orderNo);
                coreExamPaperAnswerList.add(coreExamPaperAnswer);
                orderNo++;
            }
        }

        getDao().insert(coreExamPaper);

        limsCoreExamPaperAnswerService.getDao().insert(coreExamPaperAnswerList);
    }

    private List<LimsCoreQuestionBean> getRandomQuestion(List<LimsCoreQuestionBean> questionList, Long n) {

        List<Integer> randomIndexList = RandomUtils.shuffle(0, questionList.size());

        List<LimsCoreQuestionBean> questionList4Return = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            questionList4Return.add(questionList.get(randomIndexList.get(i)));
        }

        return questionList4Return;
    }

    @Override
    public Page<LimsCoreExamBean> searchExamPaperCode(RestJsonWrapperBean wrapperBean) {
        return limsCoreExamService.selectPagination(() -> getDao().searchExamPaperCode(wrapperBean.extractMapFilter()), wrapperBean.extractPageRowBounds());
    }
}